use std::collections::HashMap;

use axum::{
    extract::{Query, State},
    response::IntoResponse,
    Json,
};

use crate::app_state::state::SharedState;
use crate::types::{
    channel::{Request, Response},
    idea::*,
};
use crate::utils::response::*;

use super::utils::send_to_iblog_grpc_client_and_wait;

pub async fn add(
    State(state): State<SharedState>,
    Json(idea): Json<AddRequest>,
) -> impl IntoResponse {
    dbg!("Idea add: {}", &idea);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaAdd(idea)).await {
        Ok(rsp) => {
            if let Response::IdeaAdd(id) = rsp {
                ok_with_message_data("新增博客成功", id)
            } else {
                panic!("Wrong idea add response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}

pub async fn get(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    dbg!("Getting idea: {}", id);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaGet(id)).await {
        Ok(rsp) => {
            if let Response::IdeaGet(idea) = rsp {
                ok_with_data(idea)
            } else {
                panic!("Wrong idea get response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}

pub async fn get_multiple(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    let count = *params.get("count").unwrap();

    dbg!("Getting ideas: {}/{}", id, count);

    match send_to_iblog_grpc_client_and_wait(
        state.clone(),
        Request::IdeasGet(GetMutipleRequest { id, count }),
    )
    .await
    {
        Ok(rsp) => {
            if let Response::IdeasGet(ideas) = rsp {
                ok_with_data(ideas)
            } else {
                panic!("Wrong ideas get response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}

pub async fn update(
    State(state): State<SharedState>,
    Json(idea): Json<UpdateRequest>,
) -> impl IntoResponse {
    dbg!("Updating idea: {}", &idea);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaUpdate(idea)).await {
        Ok(_) => ok(),
        Err(err) => error_with_message(&err),
    }
}

pub async fn delete(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    dbg!("Deleting idea: {}", id);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaDelete(id)).await {
        Ok(_) => ok(),
        Err(err) => error_with_message(&err),
    }
}

pub async fn view_inc(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    dbg!("Idea view inc: {}", id);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaViewInc(id)).await {
        Ok(rsp) => {
            if let Response::Views(views) = rsp {
                ok_with_data(views)
            } else {
                panic!("Wrong idea view inc response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}

pub async fn star_inc(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    dbg!("Idea view inc: {}", id);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaStarInc(id)).await {
        Ok(rsp) => {
            if let Response::Views(stars) = rsp {
                ok_with_data(stars)
            } else {
                panic!("Wrong idea star inc response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}

pub async fn star_dec(
    State(state): State<SharedState>,
    params: Query<HashMap<String, u32>>,
) -> impl IntoResponse {
    let id = *params.get("id").unwrap();
    dbg!("Idea view inc: {}", id);

    match send_to_iblog_grpc_client_and_wait(state.clone(), Request::IdeaStarDec(id)).await {
        Ok(rsp) => {
            if let Response::Views(stars) = rsp {
                ok_with_data(stars)
            } else {
                panic!("Wrong idea star dec response type");
            }
        }
        Err(err) => error_with_message(&err),
    }
}
